/*
 * Copyright (C) 2021 NaviTech
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @ingroup     core_internal
 * @{
 *
  * @file         base_types.h
  * @brief
  * @note
  * @author       lixinliang
  * @date         2021-08-14
  *
  * @par          修改日志
  * <table>
  * <tr><th>Date        <th>Version          <th>Author                        <th>Description
  * <tr><td>2021-08-14  <td>1.0              <td>lixinliang@hopechart.com      <td>创建初始版本
  * @copyright
  */

#ifndef _BASE_TYPES_H_
#define _BASE_TYPES_H_

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef void * TSFCHandle; /**< 句柄 */

/**
 * @def         TSFCVoidCallBack
 * @brief       返回空值的回调函数.
 * @param[in]   arg  传入的参数
 */
typedef void    (*TSFCVoidCallBack)(void *arg);

/**
 * @def         TSFCBoolCallBack
 * @brief       返回布尔类型的回调函数.
 * @param[in]   arg  传入的参数
 * @returns     true false
 */
typedef bool    (*TSFCBoolCallBack)(void *arg);

/**
 * @def         TSFCInt32CallBack
 * @brief       返回Int32类型的回调函数.
 * @param[in]   arg  传入的参数
 * @returns     具体由引用定义
 */
typedef int32_t (*TSFCInt32CallBack)(void *arg);

/**
 * @def         TSFCUInt32CallBack
 * @brief       返回UInt32类型的回调函数.
 * @param[in]   arg  传入的参数
 * @returns     具体由引用定义
 */
typedef uint32_t (*TSFCUInt32CallBack)(void *arg);

/**
 * @brief Definition of status code
 */
enum TSFCStatusEnumTag
{
    kSFCEnable  = 1, /**< enable */
    kSFCDisable = 0, /**< disable */
    kSFCTrue    = 1, /**< true */
    kSFCFalse   = 0  /**< false */
};
typedef enum TSFCStatusEnumTag TSFCStatusEnum;

/**
 * @def         SFC_OFFSET_OF(TYPE, MEMBER)
 * @brief       返回 MEMBER 在 TYPE 的位置，包含padding的字节数.
 * @param[in]   TYPE  a type name (a struct or union), container of PTR
 * @param[in]   MEMBER  name of the member of TYPE which PTR points to
 * @returns     The minimal alignment of T.
 */
#define SFC_OFFSET_OF(TYPE, MEMBER) (offsetof(TYPE, MEMBER))

/**
 * @def         container_of(PTR, TYPE, MEMBER)
 * @brief       Returns the container of a pointer to a member.
 * @details     For a struct `TYPE` with a member `MEMBER`,
 *              given a pointer `PTR` to `TYPE::MEMBER` this function returns a pointer
 *              to the instance of `TYPE`.
 * @details     E.g. for `struct my_struct_t { ...; something_t n; ... } my_struct;`,
 *              `&my_struct == container_of(&my_struct.n, struct my_struct_t, n)`.
 * @param[in]   PTR      pointer to a member
 * @param[in]   TYPE     a type name (a struct or union), container of PTR
 * @param[in]   MEMBER   name of the member of TYPE which PTR points to
 * @return      Pointer to the container of PTR.
 */
#if __STDC_VERSION__ >= 201112L
#define SFC_CONTAINER_OF(PTR, TYPE, MEMBER) \
        (_Generic((PTR), \
            const __typeof__ (((TYPE *) 0)->MEMBER) *: \
                ((TYPE *) ((uintptr_t) (PTR) - offsetof(TYPE, MEMBER))), \
            __typeof__ (((TYPE *) 0)->MEMBER) *: \
                ((TYPE *) ((uintptr_t) (PTR) - offsetof(TYPE, MEMBER))) \
        ))
#elif defined __GNUC__
#define SFC_CONTAINER_OF(PTR, TYPE, MEMBER) \
        (__extension__ ({ \
            __extension__ const __typeof__ (((TYPE *) 0)->MEMBER) *__m____ = (PTR); \
            ((TYPE *) ((uintptr_t) __m____ - offsetof(TYPE, MEMBER))); \
        }))
#else
#define SFC_CONTAINER_OF(PTR, TYPE, MEMBER) \
        ((TYPE *) ((char *) (PTR) - offsetof(TYPE, MEMBER)))
#endif

/**
 * @def SFC_ARRAY_SIZE(a)
 * @brief       Calculate the number of elements in a static array.
 * @param[in]   a   Array to examine
 * @returns     The number of elements in the array a.
 */
#define SFC_ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))

/**
 * @def         SFC_ALIGN_OF(T)
 * @brief       Calculate the minimal alignment for type T.
 * @param[in]   T   Type to examine
 * @returns     The minimal alignment of T.
 */
#define SFC_ALIGN_OF(T) (offsetof(struct { char c; T t; }, t))

#ifdef __cplusplus
} // extern "C" {
#endif

#endif	// _BASE_TYPES_H_
/** @} */
